// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: qjs_dom_token_list.cpp
// Description: Bindings for DOMTokenList
//      Author: Ziming Li
//     Created: 2022-11-08
// -------------------------------------------------
// Copyright (C) 2022 MingYang Software Technology.
// -------------------------------------------------

#include "./qjs_bindings.h"

#include "blinkit/blink/renderer/bindings/core/qjs/qjs.h"
#include "blinkit/blink/renderer/bindings/core/qjs/qjs_c_function_list_entries.h"
#include "blinkit/blink/renderer/bindings/core/script_controller.h"
#include "blinkit/blink/renderer/core/dom/dom_token_list.h"

namespace BlinKit {
namespace qjs {

/**
 * https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList
 */

static JSValue Add(JSContext *ctx, JSValueConst thisVal, int argc, JSValueConst *argv)
{
    static const char kTypeError[] = "Invalid arg %d: string excepted!";

    DOMTokenList *tokens = ScriptWrappable::Cast<DOMTokenList>(thisVal);
    Context c(*ctx);
    if (1 == argc)
    {
        if (!JS_IsString(argv[0]))
            return JS_ThrowTypeError(ctx, kTypeError, 1);
        tokens->add(ToAtomicString(ctx, argv[0]), c);
    }
    else
    {
        Vector<String> v;
        for (int i = 0; i < argc; ++i)
        {
            if (!JS_IsString(argv[i]))
                return JS_ThrowTypeError(ctx, kTypeError, i + 1);
            v.append(ToWTFString(ctx, argv[i]));
        }
        tokens->add(v, c);
    }

    if (c.hadException())
        return c.ReturnException();
    return JS_UNDEFINED;
}

static JSValue GetLength(JSContext *ctx, JSValueConst thisVal)
{
    DOMTokenList *tokens = ScriptWrappable::Cast<DOMTokenList>(thisVal);
    return JS_NewUint32(ctx, tokens->length());
}

static JSValue Remove(JSContext *ctx, JSValueConst thisVal, int argc, JSValueConst *argv)
{
    static const char kTypeError[] = "Invalid arg %d: string excepted!";

    DOMTokenList *tokens = ScriptWrappable::Cast<DOMTokenList>(thisVal);
    Context c(*ctx);
    if (1 == argc)
    {
        if (!JS_IsString(argv[0]))
            return JS_ThrowTypeError(ctx, kTypeError, 1);
        tokens->remove(ToAtomicString(ctx, argv[0]), c);
    }
    else
    {
        Vector<String> v;
        for (int i = 0; i < argc; ++i)
        {
            if (!JS_IsString(argv[i]))
                return JS_ThrowTypeError(ctx, kTypeError, i + 1);
            v.append(ToWTFString(ctx, argv[i]));
        }
        tokens->remove(v, c);
    }

    if (c.hadException())
        return c.ReturnException();
    return JS_UNDEFINED;
}

JSValue CreateDOMTokenListPrototype(JSContext *ctx)
{
    static const JSCFunctionListEntry Funcs[] = {
        CFunctionEntry("add", 1, Add),
        CGetSetEntry(Strings::Length, GetLength, nullptr),
        CFunctionEntry("remove", 1, Remove)
    };

    JSValue ret = JS_NewObject(ctx);
    JS_SetPropertyFunctionList(ctx, ret, Funcs, std::size(Funcs));
    return ret;
}

} // namespace qjs
} // namespace BlinKit
